package com.lam.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lam.common.config.AppBaseConfig;
import com.lam.common.exception.BaseException;
import com.lam.common.utils.file.FileUtil;
import com.lam.common.utils.uuid.IdGen;

public class UriSchemeUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(UriSchemeUtil.class);
	
//	data: 文本数据
//	data: text/plain, ------- 文本数据
//	data: text/html, -------- HTML代码
//	data: text/html;base64, -------- base64编码的HTML代码
//	data: text/css, ---------- CSS代码
//	data: text/css;base64, ---------- base64编码的CSS代码
//	data: text/javascript, ------------ Javascript代码
//	data: text/javascript;base64, --------- base64编码的Javascript代码
//	data: image/gif;base64, ---------------- base64编码的gif图片数据
//	data: image/png;base64, -------------- base64编码的png图片数据
//	data: image/jpeg;base64, ------------- base64编码的jpeg图片数据
//	data: image/x-icon;base64, ---------- base64编码的icon图片数据UriSchemeUtil
	/** 文本数据 */
	private static final String BASE_TYPE = "data:";
	/** 前缀 */
	private static final String PREFIX_FORMAT = BASE_TYPE + "%s,";
	/** 数据类型 */
	private static final String[] DATA_TYPE_ARR = new String[] {"image/png;base64", "image/jpeg;base64", "image/gif;base64", "image/x-icon;base64", 
			"text/plain", "text/html", "text/html;base64", "text/css", "text/css;base64", "text/javascript", "text/javascript;base64"};
	
	private static final Map<String, String> DATA_TYPE_MAP;
	private static final Map<String, String> EXT_MAP;
	static {
		Map<String, String> dataTypeMap = new HashMap<String, String>();
		Map<String, String> extMap = new HashMap<String, String>();
		String ext;
		for (String type : DATA_TYPE_ARR) {
			ext = type.replace("image/", "").replace("text/", "").replace(";base64", "");
			switch (ext) {
			case "x-icon": ext = "icon";break;
			case "plain": ext = "txt";break;
			case "javascript": ext = "js";break;
			default:
			}
			dataTypeMap.put(type, ext);
			extMap.put(ext, type);
		}
		DATA_TYPE_MAP = Collections.unmodifiableMap(dataTypeMap);
		EXT_MAP = Collections.unmodifiableMap(extMap);
	}
	
	public static String convert2File(String base64) {
		
		return convert2File(base64, null, null);
	}
	
	public static String convert2File(String base64, String fileName) {
		
		return convert2File(base64, null, fileName);
	}
	
	public static String convert2File(String base64, String baseDir, String fileName) {
		
		if(StringUtils.isBlank(base64)) {
			return null;
		}
		
		baseDir = StringUtils.isBlank(baseDir) ? AppBaseConfig.me().getLocalAttachment().getAttachmentDir() : baseDir;
		fileName = StringUtils.isBlank(fileName) ? DateUtil.getDate(DateUtil.PATTERN_YYYYMMDDHHMMSS_SSS) + IdGen.genRandom(4) : fileName;
		
		String dataType = getDataType(base64);
		fileName = fileName + '.' + DATA_TYPE_MAP.get(dataType);
		String filePath = baseDir + fileName;
		if(!FileUtil.mkdir(FileUtil.getDirFromPath(filePath))) {
			logger.error("创建文件目录异常, dirPath:{}", filePath);
			throw new BaseException("生成文件异常！");
		}
		
		String contentBase64 = getContentBase64(base64, dataType);
		// 赋值文件
        InputStream in = null;
        OutputStream out = null;
        try {
        	if(dataType.contains("base64")) {
    			in = new ByteArrayInputStream(Base64Util.decodeByte(contentBase64));
    		}else {
    			in = new ByteArrayInputStream(contentBase64.getBytes());
    		}
            out = new FileOutputStream(filePath);
            FileUtil.copy(in, out);
        } catch (IOException e) {
            logger.error("Base64生成文件异常", e);
            throw new BaseException("Base64生成文件异常");
        } finally {
        	FileUtil.closeQuietly(in);
        	FileUtil.closeQuietly(out);
        }
        return filePath;
	}
	
	public static ByteArrayInputStream decode(String base64) {
		
		if(StringUtils.isBlank(base64)) {
			return null;
		}
		String dataType = getDataType(base64);
		
		String contentBase64 = getContentBase64(base64, dataType);
		
		if(dataType.contains("base64")) {
			return new ByteArrayInputStream(Base64Util.decodeByte(contentBase64));
		}
		return new ByteArrayInputStream(contentBase64.getBytes());
	}
	
	public static String encode(String filePath) {
		
		if(StringUtils.isBlank(filePath)) {
			return null;
		}
		
		String ext = FileUtil.getFileSuffix(filePath);
		ext = StringUtils.isBlank(ext)?"txt":ext;
		String dataType = EXT_MAP.get(ext);
		if(StringUtils.isBlank(ext)) {
			dataType = "text/plain";
		}
		
		FileInputStream input = null;
		ByteArrayOutputStream output = null;
		try {
			input = new FileInputStream(new File(filePath));
			output = new ByteArrayOutputStream();
			//写入流中
//        	ImageIO.write(image, IMG_FORMAT, output);
			FileUtil.copy(input, output);
			//转换成base64串
			String base64 = Base64Util.encodeByte(output.toByteArray());
			base64 = base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
			return String.format(PREFIX_FORMAT, dataType) + base64;
		} catch (Exception e) {
			logger.error("读取文件转Base64数据异常", e);
			throw new BaseException("读取文件转Base64数据异常！");
		} finally {
        	FileUtil.closeQuietly(input);
        	FileUtil.closeQuietly(output);
        }
	}
	
	public static String getContentBase64(String base64, String dataType) {
		
		if(StringUtils.isBlank(base64)) {
			return null;
		}
		
		return base64.replace(String.format(PREFIX_FORMAT, dataType), "").replace(BASE_TYPE, "");
	}
	
	public static String getDataType(String base64) {
		
		if(StringUtils.isBlank(base64)) {
			return null;
		}
		
		base64 = base64.replaceAll("\\s", "");
		String dataType = null;
		for (String type : DATA_TYPE_ARR) {
			if(base64.startsWith(String.format(PREFIX_FORMAT, type))) {
				dataType = type;
				break;
			}
		}
		if(StringUtils.isBlank(dataType) && base64.startsWith(BASE_TYPE)) {
			dataType = "text/plain";
		}
		
		if(StringUtils.isBlank(dataType)) {
			throw new BaseException("未识别的Data URI Scheme数据！");
		}
		return dataType;
	}

}
